home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / prog / dflt18.arj / POPDOWN.C < prev    next >
Text File  |  1992-10-06  |  12KB  |  381 lines

  1. /* ------------- popdown.c ----------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. static int SelectionWidth(struct PopDown *);
  6. static int py = -1;
  7.  
  8. /* ------------ CREATE_WINDOW Message ------------- */
  9. static int CreateWindowMsg(WINDOW wnd)
  10. {
  11.     int rtn, adj;
  12.     ClearAttribute(wnd, HASTITLEBAR     |
  13.                         VSCROLLBAR     |
  14.                         MOVEABLE     |
  15.                         SIZEABLE     |
  16.                         HSCROLLBAR);
  17.     /* ------ adjust to keep popdown on screen ----- */
  18.     adj = SCREENHEIGHT-1-wnd->rc.bt;
  19.     if (adj < 0)    {
  20.         wnd->rc.tp += adj;
  21.         wnd->rc.bt += adj;
  22.     }
  23.     adj = SCREENWIDTH-1-wnd->rc.rt;
  24.     if (adj < 0)    {
  25.         wnd->rc.lf += adj;
  26.         wnd->rc.rt += adj;
  27.     }
  28.     rtn = BaseWndProc(POPDOWNMENU, wnd, CREATE_WINDOW, 0, 0);
  29.     SendMessage(wnd, CAPTURE_MOUSE, 0, 0);
  30.     SendMessage(wnd, CAPTURE_KEYBOARD, 0, 0);
  31.     SendMessage(NULL, SAVE_CURSOR, 0, 0);
  32.     SendMessage(NULL, HIDE_CURSOR, 0, 0);
  33.     wnd->oldFocus = inFocus;
  34.     inFocus = wnd;
  35.     return rtn;
  36. }
  37.  
  38. /* --------- LEFT_BUTTON Message --------- */
  39. static void LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  40. {
  41.     int my = (int) p2 - GetTop(wnd);
  42.     if (InsideRect(p1, p2, ClientRect(wnd)))    {
  43.         if (my != py)    {
  44.             SendMessage(wnd, LB_SELECTION,
  45.                     (PARAM) wnd->wtop+my-1, TRUE);
  46.             py = my;
  47.         }
  48.     }
  49.     else if ((int)p2 == GetTop(GetParent(wnd)))
  50.         if (GetClass(GetParent(wnd)) == MENUBAR)
  51.             PostMessage(GetParent(wnd), LEFT_BUTTON, p1, p2);
  52. }
  53.  
  54. /* -------- BUTTON_RELEASED Message -------- */
  55. static BOOL ButtonReleasedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  56. {
  57.     py = -1;
  58.     if (InsideRect((int)p1, (int)p2, ClientRect(wnd)))    {
  59.         int sel = (int)p2 - GetClientTop(wnd);
  60.         if (*TextLine(wnd, sel) != LINE)
  61.             SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
  62.     }
  63.     else    {
  64.         WINDOW pwnd = GetParent(wnd);
  65.         if (GetClass(pwnd) == MENUBAR && (int)p2==GetTop(pwnd))
  66.             return FALSE;
  67.         if ((int)p1 == GetLeft(pwnd)+2)
  68.             return FALSE;
  69.         SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  70.         return TRUE;
  71.     }
  72.     return FALSE;
  73. }
  74.  
  75. /* --------- PAINT Message -------- */
  76. static void PaintMsg(WINDOW wnd)
  77. {
  78.     int wd;
  79.     unsigned char sep[80], *cp = sep;
  80.     unsigned char sel[80];
  81.     struct PopDown *ActivePopDown;
  82.     struct PopDown *pd1;
  83.  
  84.     ActivePopDown = pd1 = wnd->mnu->Selections;
  85.     wd = MenuWidth(ActivePopDown)-2;
  86.     while (wd--)
  87.         *cp++ = LINE;
  88.     *cp = '\0';
  89.     SendMessage(wnd, CLEARTEXT, 0, 0);
  90.     wnd->selection = wnd->mnu->Selection;
  91.     while (pd1->SelectionTitle != NULL)    {
  92.         if (*pd1->SelectionTitle == LINE)
  93.             SendMessage(wnd, ADDTEXT, (PARAM) sep, 0);
  94.         else    {
  95.             int len;
  96.             memset(sel, '\0', sizeof sel);
  97.             if (pd1->Attrib & INACTIVE)
  98.                 /* ------ inactive menu selection ----- */
  99.                 sprintf(sel, "%c%c%c",
  100.                     CHANGECOLOR,
  101.                     wnd->WindowColors [HILITE_COLOR] [FG]|0x80,
  102.                     wnd->WindowColors [STD_COLOR] [BG]|0x80);
  103.             strcat(sel, " ");
  104.             if (pd1->Attrib & CHECKED)
  105.                 /* ---- paint the toggle checkmark ---- */
  106.                 sel[strlen(sel)-1] = CHECKMARK;
  107.             len=CopyCommand(sel+strlen(sel),pd1->SelectionTitle,
  108.                     pd1->Attrib & INACTIVE,
  109.                     wnd->WindowColors [STD_COLOR] [BG]);
  110.             if (pd1->Accelerator)    {
  111.                 /* ---- paint accelerator key ---- */
  112.                 int i;
  113.                 int wd1 = 2+SelectionWidth(ActivePopDown) -
  114.                                     strlen(pd1->SelectionTitle);
  115.                 for (i = 0; keys[i].keylabel; i++)    {
  116.                     if (keys[i].keycode == pd1->Accelerator)   {
  117.                         while (wd1--)
  118.                             strcat(sel, " ");
  119.                         sprintf(sel+strlen(sel), "[%s]",
  120.                             keys[i].keylabel);
  121.                         break;
  122.                     }
  123.                 }
  124.             }
  125.             if (pd1->Attrib & CASCADED)    {
  126.                 /* ---- paint cascaded menu token ---- */
  127.                 if (!pd1->Accelerator)    {
  128.                     wd = MenuWidth(ActivePopDown)-len+1;
  129.                     while (wd--)
  130.                         strcat(sel, " ");
  131.                 }
  132.                 sel[strlen(sel)-1] = CASCADEPOINTER;
  133.             }
  134.             else
  135.                 strcat(sel, " ");
  136.             strcat(sel, " ");
  137.             sel[strlen(sel)-1] = RESETCOLOR;
  138.             SendMessage(wnd, ADDTEXT, (PARAM) sel, 0);
  139.         }
  140.         pd1++;
  141.     }
  142. }
  143.  
  144. /* ---------- BORDER Message ----------- */
  145. static int BorderMsg(WINDOW wnd)
  146. {
  147.     int i, rtn = TRUE;
  148.     WINDOW currFocus;
  149.     if (wnd->mnu != NULL)    {
  150.         currFocus = inFocus;
  151.         inFocus = NULL;
  152.         rtn = BaseWndProc(POPDOWNMENU, wnd, BORDER, 0, 0);
  153.         inFocus = currFocus;
  154.         for (i = 0; i < ClientHeight(wnd); i++)    {
  155.             if (*TextLine(wnd, i) == LINE)    {
  156.                 wputch(wnd, LEDGE, 0, i+1);
  157.                 wputch(wnd, REDGE, WindowWidth(wnd)-1, i+1);
  158.             }
  159.         }
  160.     }
  161.     return rtn;
  162. }
  163.  
  164. /* -------------- LB_CHOOSE Message -------------- */
  165. static void LBChooseMsg(WINDOW wnd, PARAM p1)
  166. {
  167.     struct PopDown *ActivePopDown = wnd->mnu->Selections;
  168.     if (ActivePopDown != NULL)    {
  169.         int *attr = &(ActivePopDown+(int)p1)->Attrib;
  170.         wnd->mnu->Selection = (int)p1;
  171.         if (!(*attr & INACTIVE))    {
  172.             if (*attr & TOGGLE)
  173.                 *attr ^= CHECKED;
  174.             PostMessage(GetParent(wnd), COMMAND,
  175.                 (ActivePopDown+(int)p1)->ActionId, p1);
  176.         }
  177.         else
  178.             beep();
  179.     }
  180. }
  181.  
  182. /* ---------- KEYBOARD Message --------- */
  183. static BOOL KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  184. {
  185.     struct PopDown *ActivePopDown = wnd->mnu->Selections;
  186.     if (wnd->mnu != NULL)    {
  187.         if (ActivePopDown != NULL)    {
  188.             int c = (int)p1;
  189.             int sel = 0;
  190.             int a;
  191.             struct PopDown *pd = ActivePopDown;
  192.  
  193.             if ((c & OFFSET) == 0)
  194.                 c = tolower(c);
  195.             a = AltConvert(c);
  196.  
  197.             while (pd->SelectionTitle != NULL)    {
  198.                 char *cp = strchr(pd->SelectionTitle,
  199.                                 SHORTCUTCHAR);
  200.                 int sc = tolower(*(cp+1));
  201.                 if ((cp && sc == c) ||
  202.                         (a && sc == a) ||
  203.                             pd->Accelerator == c)    {
  204.                     PostMessage(wnd, LB_SELECTION, sel, 0);
  205.                     PostMessage(wnd, LB_CHOOSE, sel, TRUE);
  206.                     return TRUE;
  207.                 }
  208.                 pd++, sel++;
  209.             }
  210.         }
  211.     }
  212.     switch ((int)p1)    {
  213.         case F1:
  214.             if (ActivePopDown == NULL)
  215.                 SendMessage(GetParent(wnd), KEYBOARD, p1, p2);
  216.             else 
  217.                 DisplayHelp(wnd,
  218.                     (ActivePopDown+wnd->selection)->help);
  219.             return TRUE;
  220.         case ESC:
  221.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  222.             return TRUE;
  223.         case FWD:
  224.         case BS:
  225.             if (GetClass(GetParent(wnd)) == MENUBAR)
  226.                 PostMessage(GetParent(wnd), KEYBOARD, p1, p2);
  227.             return TRUE;
  228.         case UP:
  229.             if (wnd->selection == 0)    {
  230.                 if (wnd->wlines == ClientHeight(wnd))    {
  231.                     PostMessage(wnd, LB_SELECTION,
  232.                                     wnd->wlines-1, FALSE);
  233.                     return TRUE;
  234.                 }
  235.             }
  236.             break;
  237.         case DN:
  238.             if (wnd->selection == wnd->wlines-1)    {
  239.                 if (wnd->wlines == ClientHeight(wnd))    {
  240.                     PostMessage(wnd, LB_SELECTION, 0, FALSE);
  241.                     return TRUE;
  242.                 }
  243.             }
  244.             break;
  245.         case HOME:
  246.         case END:
  247.         case '\r':
  248.             break;
  249.         default:
  250.             return TRUE;
  251.     }
  252.     return FALSE;
  253. }
  254.  
  255. /* ----------- CLOSE_WINDOW Message ---------- */
  256. static int CloseWindowMsg(WINDOW wnd)
  257. {
  258.     int rtn;
  259.     WINDOW pwnd = GetParent(wnd);
  260.     SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  261.     SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  262.     SendMessage(NULL, RESTORE_CURSOR, 0, 0);
  263.     inFocus = wnd->oldFocus;
  264.     rtn = BaseWndProc(POPDOWNMENU, wnd, CLOSE_WINDOW, 0, 0);
  265.     SendMessage(pwnd, CLOSE_POPDOWN, 0, 0);
  266.     return rtn;
  267. }
  268.  
  269. /* - Window processing module for POPDOWNMENU window class - */
  270. int PopDownProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  271. {
  272.     switch (msg)    {
  273.         case CREATE_WINDOW:
  274.             return CreateWindowMsg(wnd);
  275.         case LEFT_BUTTON:
  276.             LeftButtonMsg(wnd, p1, p2);
  277.             return FALSE;
  278.         case DOUBLE_CLICK:
  279.             return TRUE;
  280.         case LB_SELECTION:
  281.             if (*TextLine(wnd, (int)p1) == LINE)
  282.                 return TRUE;
  283.             wnd->mnu->Selection = (int)p1;
  284.             break;
  285.         case BUTTON_RELEASED:
  286.             if (ButtonReleasedMsg(wnd, p1, p2))
  287.                 return TRUE;
  288.             break;
  289.         case BUILD_SELECTIONS:
  290.             wnd->mnu = (void *) p1;
  291.             wnd->selection = wnd->mnu->Selection;
  292.             break;
  293.         case PAINT:
  294.             if (wnd->mnu == NULL)
  295.                 return TRUE;
  296.             PaintMsg(wnd);
  297.             break;
  298.         case BORDER:
  299.             return BorderMsg(wnd);
  300.         case LB_CHOOSE:
  301.             LBChooseMsg(wnd, p1);
  302.             return TRUE;
  303.         case KEYBOARD:
  304.             if (KeyboardMsg(wnd, p1, p2))
  305.                 return TRUE;
  306.             break;
  307.         case CLOSE_WINDOW:
  308.             return CloseWindowMsg(wnd);
  309.         default:
  310.             break;
  311.     }
  312.     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  313. }
  314.  
  315. /* --------- compute menu height -------- */
  316. int MenuHeight(struct PopDown *pd)
  317. {
  318.     int ht = 0;
  319.     while (pd[ht].SelectionTitle != NULL)
  320.         ht++;
  321.     return ht+2;
  322. }
  323.  
  324. /* --------- compute menu width -------- */
  325. int MenuWidth(struct PopDown *pd)
  326. {
  327.     int wd = 0, i;
  328.     int len = 0;
  329.  
  330.     wd = SelectionWidth(pd);
  331.     while (pd->SelectionTitle != NULL)    {
  332.         if (pd->Accelerator)    {
  333.             for (i = 0; keys[i].keylabel; i++)
  334.                 if (keys[i].keycode == pd->Accelerator)    {
  335.                     len = max(len, 2+strlen(keys[i].keylabel));
  336.                     break;
  337.                 }
  338.         }
  339.         if (pd->Attrib & CASCADED)
  340.             len = max(len, 2);
  341.         pd++;
  342.     }
  343.     return wd+5+len;
  344. }
  345.  
  346. /* ---- compute the maximum selection width in a menu ---- */
  347. static int SelectionWidth(struct PopDown *pd)
  348. {
  349.     int wd = 0;
  350.     while (pd->SelectionTitle != NULL)    {
  351.         int len = strlen(pd->SelectionTitle)-1;
  352.         wd = max(wd, len);
  353.         pd++;
  354.     }
  355.     return wd;
  356. }
  357.  
  358. /* ----- copy a menu command to a display buffer ---- */
  359. int CopyCommand(unsigned char *dest, unsigned char *src,
  360.                                         int skipcolor, int bg)
  361. {
  362.     unsigned char *d = dest;
  363.     while (*src && *src != '\n')    {
  364.         if (*src == SHORTCUTCHAR)    {
  365.             src++;
  366.             if (!skipcolor)    {
  367.                 *dest++ = CHANGECOLOR;
  368.                 *dest++ = cfg.clr[POPDOWNMENU]
  369.                             [HILITE_COLOR] [BG] | 0x80;
  370.                 *dest++ = bg | 0x80;
  371.                 *dest++ = *src++;
  372.                 *dest++ = RESETCOLOR;
  373.             }
  374.         }
  375.         else
  376.             *dest++ = *src++;
  377.     }
  378.     return (int) (dest - d);
  379. }
  380.  
  381.